import * as fs from 'fs';
import * as path from 'path';

import { Injectable, HttpException } from '@nestjs/common';

import { uploadConfig } from './upload.config';

@Injectable()
export class UploadService {
  private readonly uploadDir = uploadConfig.uploadDir;

  constructor() {
    if (!fs.existsSync(this.uploadDir)) {
      fs.mkdirSync(this.uploadDir, { recursive: true });
    }
  }

  async uploadFile(file: Express.Multer.File) {
    try {
      this.validateFile(file);
      const fileInfo = await this.saveFile(file);
      return fileInfo;
    } catch (error) {
      throw new HttpException(error.message || '文件上传失败', 400);
    }
  }

  async uploadFiles(files: Express.Multer.File[]) {
    try {
      if (files.length > uploadConfig.maxFiles) {
        throw new HttpException(
          `一次最多上传${uploadConfig.maxFiles}个文件`,
          400,
        );
      }

      files.forEach((file) => this.validateFile(file));

      const uploadedFiles = await Promise.all(
        files.map((file) => this.saveFile(file)),
      );

      return {
        successCount: uploadedFiles.length,
        files: uploadedFiles,
      };
    } catch (error) {
      throw new HttpException(error.message || '文件上传失败', 400);
    }
  }

  private validateFile(file: Express.Multer.File) {
    if (file.size > uploadConfig.maxFileSize) {
      throw new HttpException(uploadConfig.fileSizeErrorMessage, 400);
    }

    if (!uploadConfig.allowedMimeTypes.includes(file.mimetype)) {
      throw new HttpException(uploadConfig.fileTypeErrorMessage, 400);
    }
  }

  private async saveFile(file: Express.Multer.File) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);

    // 原文件名的基础部分（不含路径）
    const ext = path.extname(file.originalname); // 获取扩展名，例如 ".png"
    const baseName = path.basename(file.originalname, ext);

    // 把中文和特殊字符替换为下划线，只保留字母数字 - _
    const safeBaseName = baseName.replace(/[^\w\-]/g, '_');

    // 最终文件名
    // const filename = `${uniqueSuffix}-${baseName}-${ext}`;
    const filename = `${uniqueSuffix}-${file.originalname}`;

    // 保存路径（磁盘上的真实路径）
    const filepath = path.join(this.uploadDir, filename);
    fs.writeFileSync(filepath, file.buffer);

    // 返回值
    return {
      originalname: file.originalname,
      filename,
      filepath: `/static/${filename}`,
      mimetype: file.mimetype,
      size: file.size,
    };
  }
}
